package eeui.android.eeuiIdentify.module.biometric;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.biometric.BiometricConstants;
import androidx.biometric.BiometricPrompt;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;

import java.util.concurrent.Executor;

public class BiometricManager {
    private static final BiometricManager mManager = new BiometricManager();
    private androidx.biometric.BiometricManager mBiometricManager;

    private BiometricManager() {
    }

    /**
     * 初始化
     *
     * @param context
     * @return
     */
    public static BiometricManager init(@NonNull Context context) {
        mManager.initBiometricManager(context);
        return mManager;
    }

    /**
     * 初始化BiometricManager
     *
     * @param context
     */
    private void initBiometricManager(@NonNull Context context) {
        if (mBiometricManager == null) {
            mBiometricManager = androidx.biometric.BiometricManager.from(context);
        }
    }

    private Handler handler = new Handler();

    private Executor executor = new Executor() {
        @Override
        public void execute(Runnable command) {
            handler.post(command);
        }
    };

    private Callback authenticationCallback = new Callback();

    /**
     * 识别回调类
     */
    private static class Callback extends BiometricPrompt.AuthenticationCallback {
        private BiometricCallback callback;

        public void setCallback(BiometricCallback callback) {
            this.callback = callback;
        }

        @Override
        public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
            Log.i("jinhui", "onAuthenticationError: " + errorCode + "---" + errString);
            switch (errorCode) {
                case BiometricConstants.ERROR_CANCELED:
                case BiometricConstants.ERROR_USER_CANCELED:
                    if (callback != null) {
                        callback.onCanceled();
                    }
                    break;
                case BiometricConstants.ERROR_NEGATIVE_BUTTON:
                    if (callback != null) {
                        callback.onNegativeButton();
                    }
                    break;
                default:
                    if (callback != null) {
                        callback.onError(errString + "");
                    }
                    break;
            }
        }

        @Override
        public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
            if (callback != null) {
                callback.onSucceeded();
            }
        }

        @Override
        public void onAuthenticationFailed() {
            if (callback != null) {
                callback.onFailed();
            }
        }
    }

    /**
     * 判断是否可以使用生物识别
     *
     * @return
     */
    public boolean isCanAuthenticate() {
        if (mBiometricManager == null) {
            throw new NullPointerException("no init()");
        }
        int canAuthenticate = mBiometricManager.canAuthenticate();
        boolean isCan = false;
        switch (canAuthenticate) {
            case androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS:
                //App可以使用生物识别技术进行身份验证。
                isCan = true;
                break;
            case androidx.biometric.BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
                //该设备没有可用的生物特征。
                break;
            case androidx.biometric.BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
                //目前还没有生物特征。
                break;
            case androidx.biometric.BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
                //该用户没有将任何生物认证与他们的帐户关联。
                break;
        }
        return isCan;
    }

    /**
     * 开始显示识别窗口
     *
     * @param activity
     * @param builder
     * @param callback
     */
    public void showBiometricPrompt(@NonNull FragmentActivity activity, @NonNull Builder builder, final BiometricCallback callback) {
        show(activity, builder, callback);
    }

    /**
     * 开始显示识别窗口
     *
     * @param fragment
     * @param builder
     * @param callback
     */
    public void showBiometricPrompt(@NonNull Fragment fragment, @NonNull Builder builder, final BiometricCallback callback) {
        show(fragment, builder, callback);
    }

    private void show(@NonNull Object object, @NonNull Builder builder, final BiometricCallback callback) {
        if (mBiometricManager == null) {
            throw new NullPointerException("no init()");
        }
        if (TextUtils.isEmpty(builder.title)) {
            throw new NullPointerException("title is null");
        }
        if (!isCanAuthenticate()) {
            return;
        }
        BiometricPrompt biometricPrompt = null;
        Activity activity = null;
        if (object instanceof FragmentActivity) {
            activity = (FragmentActivity) object;
            authenticationCallback.setCallback(callback);
            biometricPrompt = new BiometricPrompt((FragmentActivity) object, executor, authenticationCallback);
        } else if (object instanceof Fragment) {
            activity = ((Fragment) object).getActivity();
            authenticationCallback.setCallback(callback);
            biometricPrompt = new BiometricPrompt((Fragment) object, executor, authenticationCallback);
        }
        if (biometricPrompt != null) {
            if (TextUtils.isEmpty(builder.negativeButtonText)) {
                builder.negativeButtonText = "Cancel";
            }
            BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
                    .setTitle(builder.title)
                    .setSubtitle(builder.subtitle)
                    .setNegativeButtonText(builder.negativeButtonText)
                    .build();
            // Displays the "log in" prompt.
            biometricPrompt.authenticate(promptInfo);
        }
    }

    public static class Builder {
        private String title;
        private String subtitle;
        private String negativeButtonText;


        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }

        public Builder setSubtitle(String subtitle) {
            this.subtitle = subtitle;
            return this;
        }

        public Builder setNegativeButtonText(String negativeButtonText) {
            this.negativeButtonText = negativeButtonText;
            return this;
        }
    }
}
